package com.pai4j.ugc.service.moment;

import com.pai4j.common.bean.PAIPageResponseBeanUtil;
import com.pai4j.common.constants.MomentConstants;
import com.pai4j.common.enums.messagequeue.MessageQueueEnum;
import com.pai4j.common.exception.BusinessException;
import com.pai4j.common.helper.SessionHelper;
import com.pai4j.common.service.messagequeue.producer.MessageQueueProducer;
import com.pai4j.common.util.JsonUtil;
import com.pai4j.common.util.RedisUtil;
import com.pai4j.common.util.TransactionSyncManagerUtil;
import com.pai4j.domain.dto.queue.MomentPublishMessageDTO;
import com.pai4j.domain.dto.queue.MomentEsSyncQueueDTO;
import com.pai4j.domain.vo.request.request.MomentSaveOrUpdateVO;
import com.pai4j.domain.vo.response.moment.MomentLinkVO;
import com.pai4j.domain.vo.response.moment.MomentMediaVO;
import com.pai4j.domain.vo.response.moment.MomentVO;
import com.pai4j.domain.vo.response.moment.MomentDetailVO;
import com.pai4j.domain.vo.response.UserBaseResponseInfoVO;
import com.pai4j.domain.vo.response.subjectaccount.ArticleBaseResponseVO;
import com.pai4j.domain.vo.response.subjectaccount.SubjectBaseResponseVO;
import com.pai4j.remote.act.ICommentClient;
import com.pai4j.remote.user.UserServiceClient;
import com.pai4j.ugc.repository.dao.IMomentDAO;
import com.pai4j.ugc.repository.entity.MomentEntity;
import com.pai4j.ugc.repository.entity.MomentLinkEntity;
import com.pai4j.ugc.repository.entity.MomentMediaEntity;
import com.pai4j.ugc.repository.dao.IMomentAiContentDAO;
import com.pai4j.ugc.repository.entity.MomentAiContentEntity;
import com.pai4j.domain.vo.response.moment.AiContent;
import com.pai4j.ugc.service.AccountService;
import com.pai4j.remote.act.IResourceBehaviorClient;
import com.pai4j.domain.vo.request.request.act.ResourceBehaviorRequestVO;
import com.pai4j.common.bean.PAIResponseBean;
import com.pai4j.common.bean.PAIResponseBeanUtil;
import com.pai4j.common.constants.ResourceBehaviorConstants;

import jakarta.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import com.pai4j.common.enums.RedisKeyEnum;

import java.util.*;
import java.util.stream.Collectors;

/**
 *  @author:  CYM-pai
 */
@Service
public class MomentService {


    @Resource
    private IMomentDAO momentDAO;
    @Resource
    private MomentMediaService momentMediaService;
    @Resource
    private MomentLinkService momentLinkService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private IMomentAiContentDAO momentAiContentDAO;

    @Resource
    private MessageQueueProducer<MomentPublishMessageDTO, Long> messageQueueProducer;

    @Resource
    private AccountService accountService;

    @Resource
    private IResourceBehaviorClient resourceBehaviorClient;


    @Autowired
    private MessageQueueProducer<MomentEsSyncQueueDTO, Long> esMessageQueueProducer;


    /**
     * π圈动态发布
     *
     * @param momentSaveOrUpdate
     * @return
     */
    @Transactional
    public Long publish(MomentSaveOrUpdateVO momentSaveOrUpdate) {

        /**
         * 1. 持久化
         * 1.1 π圈动态数据持久化
         * 1.2 动态资源持久化
         * 1.3 链接数据持久化
         */
        MomentEntity moment = this.convert(momentSaveOrUpdate);
        moment = momentDAO.save(moment);
        Long momentId = moment.getId();
        // 持久化图片、视频媒体资源数据
        momentMediaService.saveMomentMedia(momentId, momentSaveOrUpdate);
        // 持久化π圈动态连接数据
        momentLinkService.saveMomentLink(momentId, momentSaveOrUpdate);
        /**
         * 2. 动态详情缓存（redis）
         */
        MomentVO momentVO = this.refreshMomentCache(momentId);
        /**
         * 3. mq
         * 3.1
         * 图片、视频媒体资源信息提取
         * 连接解析
         * ip归属地解析
         * 3.2 大模型内容审核
         * 3.3 刷新/修改动态状态
         * 3.4 写扩散（把当前动态写入到所有粉丝时间线DB、Redis）
         */
        MomentPublishMessageDTO messageDTO = new MomentPublishMessageDTO();
        messageDTO.setMoment(momentVO);
        messageQueueProducer.send(MessageQueueEnum.QUEUE_MOMENT_PUBLISH, messageDTO);
        // ES 同步：事务提交后发送
        TransactionSyncManagerUtil.registerSynchronization(() -> {
            try {
                MomentVO vo = this.getMomentFromCache(momentId);
                if (vo != null) {
                    MomentEsSyncQueueDTO esMsg = new MomentEsSyncQueueDTO();
                    esMsg.setMomentId(momentId);
                    esMsg.setMomentJson(JsonUtil.toJsonString(vo));
                    esMessageQueueProducer.send(MessageQueueEnum.QUEUE_MOMENT_SYNC_ES, esMsg);
                }
            } catch (Exception ignore) {
            }
        });
        return moment.getId();
    }



    /**
     * 获取单条动态详情
     *
     * @param momentId
     * @return
     */
    public MomentVO getMomentFromCache(Long momentId) {

        String cacheKey = this.momentBaseCacheKey(momentId);
        String cache = redisUtil.get(cacheKey);
        if (StringUtils.isBlank(cache)) {
            MomentEntity momentEntity = momentDAO.findById(momentId).orElse(null);
            return this.convert(momentEntity);
        }
        return JsonUtil.fromJson(cache, MomentVO.class);
    }

        /**
     * 批量查询动态详情
     *
     * @param momentIds 动态ID列表
     * @return 动态详情列表
     */
    public List<MomentVO> batchGetMomentFromCache(List<Long> momentIds) {

        if (CollectionUtils.isEmpty(momentIds)) {
            return Collections.emptyList();
        }

        List<MomentVO> moments = new ArrayList<>();

        // 构造缓存key列表
        List<String> keys = momentIds.stream().map(this::momentBaseCacheKey).collect(Collectors.toList());
        // 批量从redis获取缓存数据
        List<String> caches = redisUtil.mget(keys);
        for (int i = 0; i < momentIds.size(); i++) {
            Long momentId = momentIds.get(i);
            String cache = caches.get(i);
            if (StringUtils.isNotBlank(cache)) {
                // 缓存命中，直接反序列化
                MomentVO cached = JsonUtil.fromJson(cache, MomentVO.class);
                // 对旧版或不完整缓存做兜底刷新
                if (cached == null
                        || cached.getAuthorInfo() == null
                        || cached.getDetail() == null
                        || cached.getPublishTime() == 0L) {
                    moments.add(this.refreshMomentCache(momentId));
                } else {
                    moments.add(cached);
                }
            } else {
                // 缓存未命中，从数据库加载并刷新缓存
                moments.add(this.refreshMomentCache(momentId));
            }
        }
        return moments;
    }

    /**
     * 刷新单个动态缓存
     *
     * @param momentId 动态ID
     * @return 动态详情VO对象
     */
    public MomentVO refreshMomentCache(Long momentId) {

        MomentEntity moment = momentDAO.findById(momentId).orElse(null);
        if (moment == null) {
            return null;
        }
        List<MomentMediaEntity> medias = null;

        if (moment.isIncludeImages()) {
            medias = momentMediaService.medias(momentId, MomentConstants.MediaType.IMAGE.getType());
        }
        if (moment.isIncludeVideo()) {
            medias = momentMediaService.medias(momentId, MomentConstants.MediaType.VIDEO.getType());
        }
        MomentLinkEntity link = null;
        if (moment.isIncludeLink()) {
            link = momentLinkService.getLink(momentId);
        }
        return this.refreshMomentCache(moment, medias, link);
    }

    /**
     * 刷新动态缓存
     *
     * @param moment 动态实体
     * @param momentMedias 动态媒体列表
     * @param linkEntity 动态链接实体
     * @return 动态详情VO对象
     */
    private MomentVO refreshMomentCache(MomentEntity moment,
                                        List<MomentMediaEntity> momentMedias,
                                        MomentLinkEntity linkEntity) {
        if (moment == null) {
            return null;
        }
        // 转换为VO对象
        MomentVO momentVO = this.convertVo(moment, momentMedias, linkEntity);
        // 补充作者信息
        try {
            UserBaseResponseInfoVO authorInfo = accountService.accountInfo(moment.getAuthor());
            momentVO.setAuthorInfo(authorInfo);
        } catch (Exception ignore) {}
        // 构建详情信息（聚合互动等数据）
        try {
            MomentDetailVO detail = new MomentDetailVO();
            // 点赞数量
            ResourceBehaviorRequestVO likeCountReq = new ResourceBehaviorRequestVO();
            likeCountReq.setUserId("system");
            likeCountReq.setBehaviorType(ResourceBehaviorConstants.BehaviorType.LIKE.name());
            likeCountReq.setResourceType(String.valueOf(ResourceBehaviorConstants.ResourceType.MOMENT));
            likeCountReq.setResourceId(moment.getId());
            PAIResponseBean<Long> likeCountResp = resourceBehaviorClient.countBehavior(likeCountReq);
            if (PAIResponseBeanUtil.isOk(likeCountResp)) {
                detail.setLikeCount(likeCountResp.getData());
            } else {
                detail.setLikeCount(0L);
            }
            // 评论数量暂不从资源行为统计，默认0（可后续接入评论服务统计）
            detail.setCommentCount(0L);
            // 是否点赞与当前用户相关，不缓存（保持null）
            momentVO.setDetail(detail);
        } catch (Exception ignore) {}

        String momentCacheKey = this.momentBaseCacheKey(moment.getId());
        // 写入redis缓存
        redisUtil.set(momentCacheKey, JsonUtil.toJsonString(momentVO),
                RedisKeyEnum.MOMENT_BASE_CACHE.getExpireTime());
        return momentVO;
    }

    /**
     * 将动态实体转换为VO对象
     *
     * @param moment 动态实体
     * @param momentMedias 动态媒体列表
     * @param linkEntity 动态链接实体
     * @return 动态详情VO对象
     */
    private MomentVO convertVo(MomentEntity moment,
                               List<MomentMediaEntity> momentMedias,
                               MomentLinkEntity linkEntity) {

        MomentVO momentVO = new MomentVO();
        BeanUtils.copyProperties(moment, momentVO);
        momentVO.setPublishTime(moment.getCreateDate().getTime());
        if (moment.isIncludeImages()) {
            // 转换图片列表
            List<MomentMediaVO> imagesVo = momentMedias.stream().map(img -> {
                MomentMediaVO image = new MomentMediaVO();
                BeanUtils.copyProperties(img, image);
                return image;
            }).collect(Collectors.toList());
            momentVO.setImages(imagesVo);
        }
        // 反序列化标签
        try {
            if (org.apache.commons.lang3.StringUtils.isNotBlank(moment.getTags())) {
                momentVO.setTags(JsonUtil.fromJson(moment.getTags(), new com.fasterxml.jackson.core.type.TypeReference<java.util.List<String>>(){}));
            }
        } catch (Exception ignore) {}
        if (moment.isIncludeVideo()) {
            // 转换视频信息
            MomentMediaEntity video = momentMedias.get(0);
            MomentMediaVO videoVo = new MomentMediaVO();
            BeanUtils.copyProperties(video, videoVo);
            momentVO.setVideo(videoVo);
        }
        if (moment.isIncludeLink()) {
            // 转换链接信息
            MomentLinkVO linkVO = new MomentLinkVO();
            BeanUtils.copyProperties(linkEntity, linkVO);
            momentVO.setLink(linkVO);
        }
        // 填充AI内容
        try {
            MomentAiContentEntity ai = momentAiContentDAO.findByMomentId(moment.getId()).orElse(null);
            if (ai != null) {
                AiContent aiContent = new AiContent();
                aiContent.setQualityScore(ai.getQualityScore());
                aiContent.setSentiment(ai.getSentiment());
                aiContent.setKeywords(JsonUtil.fromJson(ai.getKeywords(), String[].class));
                aiContent.setSummary(ai.getSummary());
                momentVO.setAiContent(aiContent);
            }
        } catch (Exception e) {
            // 不中断主流程
        }
        return momentVO;
    }

    /**
     * 构造动态缓存key
     *
     * @param momentId 动态ID
     * @return 缓存key
     */
    private String momentBaseCacheKey(Long momentId) {

        return RedisKeyEnum.MOMENT_BASE_CACHE.getKey(String.valueOf(momentId));
    }


    /**
     * 将MomentSaveOrUpdateVO对象转换为MomentEntity对象
     *
     * @param momentSaveOrUpdate 待转换的VO对象，包含动态的基本信息
     * @return 转换后的MomentEntity对象
     */
    private MomentEntity convert(MomentSaveOrUpdateVO momentSaveOrUpdate) {
        MomentEntity moment;
        Long momentId = momentSaveOrUpdate.getId();
        if (momentId != null) {
            // 更新操作：根据ID查找现有动态，并验证权限
            moment = momentDAO.findById(momentSaveOrUpdate.getId()).orElse(null);
            Assert.notNull(moment, "动态不存在");
            Assert.isTrue(ObjectUtils.equals(momentSaveOrUpdate.getAuthor(), moment.getAuthor()), "无操作权限");
        } else {
            // 新增操作：创建新的动态实体并设置初始属性
            moment = new MomentEntity();
            moment.setStatus(MomentConstants.MomentStatusEnum.NEW.getStatus());
            moment.setAuthor(momentSaveOrUpdate.getAuthor());
            moment.setIp(momentSaveOrUpdate.getIp());
            moment.setCreateDate(new Date());
        }
        // 设置动态内容和媒体类型标识
        moment.setContent(momentSaveOrUpdate.getContent());
        // 标签：前端传 List<String>，实体存 JSON 字符串，DB 非空约束，默认 []
        try {
            java.util.List<String> tags = momentSaveOrUpdate.getTags();
            moment.setTags(tags == null ? "[]" : JsonUtil.toJsonString(tags));
        } catch (Exception e) {
            moment.setTags("[]");
        }
        moment.setIncludeImages(momentSaveOrUpdate.includeImage());
        moment.setIncludeVideo(momentSaveOrUpdate.includeVideo());
        moment.setIncludeLink(momentSaveOrUpdate.includeLink());
        return moment;
    }

    public PAIPageResponseBeanUtil<MomentVO> pageAuthor(Integer pageNo, Integer pageSize, String author) {
        // 构建分页请求并查询DB
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "id"));
        Page<MomentEntity> momentEntities = momentDAO.findByAuthor(author, pageable);
        if (momentEntities == null || CollectionUtils.isEmpty(momentEntities.getContent())) {
            return PAIPageResponseBeanUtil.success(pageNo, pageSize, 0L, Collections.emptyList());
        }
        // 按照查询结果顺序收集ID
        List<Long> ids = momentEntities.getContent().stream()
                .map(MomentEntity::getId)
                .collect(Collectors.toList());
        // 走缓存批量获取完整MomentVO（包含作者信息、媒体、发布时间等）
        List<MomentVO> moments = this.batchGetMomentFromCache(ids);
        return PAIPageResponseBeanUtil.success(pageNo, pageSize, momentEntities.getTotalElements(), moments);
    }


    /**
     * 将MomentEntity对象转换为MomentVO对象
     *
     * @param momentEntity 待转换的MomentEntity对象
     * @return 转换后的MomentVO对象
     */
    private MomentVO convert(MomentEntity momentEntity){
        MomentVO momentVO = new MomentVO();
        BeanUtils.copyProperties(momentEntity,momentVO);
        return momentVO;
    }

}
